<template>
  <PopoverModal
    v-model:visible="visible"
    :placement="placement"
    @ok="onOk"
    @cancel="onCancel"
  >
    <template #content>
      <div style="width: 450px">
        <a-form ref="formRef" layout="vertical" :model="formData">
          <a-form-item label="元素类型" required name="type" :rules="rules" :validate-first="true">
            <TypeSelect v-model:value="formData"/>
          </a-form-item>
          <ScaleItem v-if="showDouble" v-model:value="formData.scale" />
          <StringItem v-else-if="showString" v-model:value="formData.expands.maxLength" />
          <BooleanItem v-else-if="showBoolean" v-model:value="formData.boolean" name="boolean"/>
          <DateItem v-else-if="showDate" v-model:value="formData.format"/>
          <EnumItem ref="enumTableRef" v-else-if="showEnum" v-model:value="formData.enum.elements"/>
          <a-form-item v-else-if="showArray" label="子元素类型" required :name="['elementType','type']" :rules="[{ required: true, message: '请选择子元素类型'}]">
            <TypeSelect  v-model:value="formData.elementType" :filter="['array', 'object']" />
          </a-form-item>
        </a-form>
      </div>
    </template>
    <slot>
      <a-button type="link" :disabled="disabled" style="padding: 0">
        <template #icon>
          <AIcon type="EditOutlined" :class="{'table-form-required-aicon': !value.type}"/>
        </template>
      </a-button>
    </slot>
  </PopoverModal>
</template>

<script setup name="MetadataArray">
import { PopoverModal, TypeSelect } from '../index'
import ScaleItem from '../Double/ScaleItem.vue'
import StringItem from '../String/Item.vue'
import BooleanItem from '../Boolean/Item.vue'
import DateItem from '../Date/Item.vue'
import EnumItem from '../Enum/Item.vue'
import {cloneDeep, pick} from 'lodash-es'
import {Form} from "ant-design-vue";

const emit = defineEmits(['update:value', 'cancel', 'confirm']);

const props = defineProps({
  value: {
    type: Object,
    default: () => ({}),
  },
  unitOptions: {
    type: [Array, Function],
    default: () => []
  },
  placement: {
    type: String,
    default: 'top',
  },
  disabled: {
    type: Boolean,
    default:false
  }
});

const formItemContext = Form.useInjectFormItemContext();

const formRef = ref()
const enumTableRef = ref()
const visible = ref(false)
const formData = reactive({
  type: props.value?.type,
  scale: props.value?.scale,
  expands: {
    maxLength: props.value?.maxLength || props.value?.expands?.maxLength,
  },
  boolean: {
    trueText: props.value?.trueText || '是',
    trueValue: props.value?.trueValue || 'true',
    falseText: props.value?.falseText || '否',
    falseValue: props.value?.falseValue || 'false',
  },
  format: props.value?.format,
  enum: {
    multiple: props.value?.multiple,
    elements: cloneDeep(props.value?.elements) || [],
  },
  elementType: props.value?.type === 'array' ? props.value.elementType : {
    type: undefined
  }
});

const showDouble = computed(() => {
  return ['float', 'double'].includes(formData.type)
})

const showString = computed(() => {
  return ['string', 'password'].includes(formData.type)
})

const showBoolean = computed(() => {
  return formData.type === 'boolean'
})

const showDate = computed(() => {
  return formData.type === 'date'
})

const showEnum = computed(() => {
  return formData.type === 'enum'
})

const showArray = computed(() => {
  return formData.type === 'array'
})

const rules = [
  {
    validator(_, value) {
      if (!value) {
        return Promise.reject('请选择元素类型');
      }
      return Promise.resolve();
    },
    trigger: 'change',
  },
];

const typeChange = (e) => {
  if (['float', 'double'].includes(e)) {
    formData.scale = 2;
  }
};

const initValue = () => {
  formData.type = props.value?.type;
  formData.scale = props.value?.scale;
  formData.expands.maxLength = props.value?.maxLength || props.value?.expands?.maxLength;
  formData.boolean = {
    trueText: props.value?.trueText || '是',
    trueValue: props.value?.trueValue || 'true',
    falseText: props.value?.falseText || '否',
    falseValue: props.value?.falseValue || 'false',
  };
  formData.format = props.value?.format;
  formData.enum = {
    multiple: props.value?.multiple,
    elements: cloneDeep(props.value?.elements || []),
  };

  formData.elementType = props.value?.type === 'array' ? props.value.elementType : {
    type: undefined
  }
};

const handleValue = (type, data) => {
  let newObject = {};
  switch (type) {
    case 'float':
    case 'double':
      newObject = pick(data, 'scale');
      break;
    case 'boolean':
      newObject = { ...data.boolean };
      break;
    case 'enum':
      newObject.elements = data.enum.elements;
      break;
    case 'string':
    case 'password':
      newObject = pick(data, 'expands');
      break;
    case 'date':
      newObject = pick(data, 'format');
      break;
    case 'array':
      newObject = pick(data, 'elementType')
  }

  return {
    type: type,
    ...newObject,
  };
};

const onOk = async () => {
  const data = await formRef.value.validate()
  let enumTable = true
  if (enumTableRef.value) {
    enumTable = !!(await enumTableRef.value.validate())
  }
  if (data && enumTable) {

    visible.value = false
    const _value = handleValue(formData.type, formData)
    emit('update:value', _value);
    emit('confirm', _value);
    formItemContext.onFieldChange()
  }
}

const onCancel = () => {
  formRef.value?.resetFields();
  initValue();
  emit('cancel');
}

watch(() => JSON.stringify(props.value), () => {
  initValue()
})

</script>

<style scoped>

</style>
